/**
 *Copyright [2010] [lcj(caijunlu@gmail.com)]
 *Licensed under the Apache License, Version 2.0 (the "License");
 *you may not use this file except in compliance with the License. 
 *You may obtain a copy of the License at 
 *             http://www.apache.org/licenses/LICENSE-2.0 
 *Unless required by applicable law or agreed to in writing, 
 *software distributed under the License is distributed on an "AS IS" BASIS, 
 *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
 *either express or implied. See the License for the specific language governing permissions and limitations under the License
 */
package org.independent.servlet.session.manager;

import java.lang.System;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.independent.servlet.session.exception.ServletSessionException;
import org.independent.servlet.session.service.ContextHolderFactory;
import org.independent.servlet.session.util.ManagerBase;
import org.independent.servlet.session.util.StringUtil;

/**
 * manage the session's id
 * 
 * @author lcj
 * 
 */
public class SessionIdManager {
	private static long sessionOuttime;
	private static String serverMemberNo = "";

	public SessionIdManager(final long sessionOuttime,
			final String serverMemberNo) {
		SessionIdManager.sessionOuttime = sessionOuttime;
		SessionIdManager.serverMemberNo = serverMemberNo;
	}

	static private String sessionIdName = SessionsManager.sessionIdName;

	final public String getSessionIdRequest(HttpServletRequest request) {
		if (sessionIdName == null) {
			throw new ServletSessionException("sessionIdName can't be null");
		}
		String sessionId = null;
		Cookie[] cookies = request.getCookies();
		// TODO Single sign on by cookie
		if (cookies != null && cookies.length > 0) {
			for (Cookie sCookie : cookies) {
				if (sCookie.getName().equalsIgnoreCase(sessionIdName)) {
					if (sCookie.getValue().indexOf("@") > -1) {
						return sCookie.getValue();
					}
				}
			}
		}
		final String uri = request.getRequestURI() + "";
		if (!StringUtil.isBlank(uri)) {
			sessionId = uri.substring(uri.indexOf(sessionIdName + "=")
					+ sessionIdName.length() + 1);
		}
		if (StringUtil.isBlank(sessionId)) {
			// TODO handle web server default sessionIdName server
			sessionId = request.getAttribute(SessionsManager.sessionIdName)
					+ "";
			if (!StringUtil.isBlank(sessionId)
					&& !sessionId.equalsIgnoreCase("null")) {
				changeSessionIdCommitType();
			}
		} else if (!sessionId.equalsIgnoreCase("null")) {
			changeSessionIdCommitType();
		}
		if (sessionId.indexOf("*") == -1 || sessionId.indexOf("@") == -1)
			return "";
		return sessionId;

	}

	/**
	 * use ManagerBase and add serverMemberNo to create new session's id
	 * 
	 * @return
	 */
	final public String createSessionId() {
		final ManagerBase managerBase = new ManagerBase();
		return (serverMemberNo.equals("") ? "" : (serverMemberNo + "*"))
				+ managerBase.generateSessionId();
	}

	/**
	 * if the session's id commit form client by URL or Attribute of request,the
	 * default type is be changed
	 * 
	 * @see org.independent.servlet.session.interceptor.ServletServiceInterceptor
	 */
	final private void changeSessionIdCommitType() {
		ContextHolderFactory.getServiceContextHolder().getContext()
				.setSessionIdCommitType(1);
	}

	/**
	 * this sessionId get from client ,Separate the last access from server time
	 * and check it not use split to get better performance
	 * 
	 * @param sessionId
	 * @return
	 * @throws ServletSessionException
	 */
	final public String checkSessionTime(String sessionId)
			throws ServletSessionException {
		int position = sessionId.indexOf("@");
		if (position != -1) {
			if (System.currentTimeMillis()
					- Long.parseLong(sessionId.substring(position + 1)) < sessionOuttime + 1)
				return sessionId.substring(0, position);
			throw new ServletSessionException("this session is time out!!");
		}
		throw new ServletSessionException("session id is error!!");
	}

	/**
	 * Format the sessionId to append current time
	 * 
	 * @param sessionId
	 * @return
	 */
	final public String formateSessionId(String sessionId) {
		if (sessionId.indexOf("@") == -1)
			return sessionId + "@" + System.currentTimeMillis();
		return sessionId;
	}
}
